package com.gzrobot.webCapTest.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.thread.NamedThreadFactory;
import com.github.sarxos.webcam.Webcam;
import com.gzrobot.gzCommon.utils.ThrowableUtil;
import com.gzrobot.webCapTest.model.query.CaptureQuery;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author : Cmy
 * @date : 2025-05-21 9:12
 */
@Slf4j
public class CaptureUtils {

    public static final Map<String, Webcam> FLAG_WEBCAM_MAP = new ConcurrentHashMap<>();

    public static final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                4,
                5,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(50000),//允许排队50000张图片 thumbnail 处理1000张 大概需要 10-20s 10000 -> 200s
                new NamedThreadFactory("webCapture", false),
                new ThreadPoolExecutor.AbortPolicy());

    public static void init() {
        List<Webcam> webcams = Webcam.getWebcams();
        for (Webcam webcam : webcams) {
            String name = webcam.getName();
            log.info("initialize " + name);
            webcam.setCustomViewSizes(new Dimension(4656, 3496));
            webcam.setViewSize(new Dimension(4656, 3496));
            webcam.open();
            FLAG_WEBCAM_MAP.put(name, webcam);
        }

        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            for (Webcam webcam : webcams) {
                if (webcam != null && webcam.isOpen()) {
                    log.info("close camera:{} release resource", webcam.getName());
                    webcam.close();
                }
            }
        }));
    }

    public static boolean captureByWay(CaptureQuery captureQuery) {
        String way = captureQuery.getWay();

        String deviceFlag = captureQuery.getDeviceFlag();
        String targetPath = captureQuery.getTargetPath();
        Webcam webcam = FLAG_WEBCAM_MAP.get(deviceFlag);
        if (webcam != null) {
            try {

                String name = webcam.getDevice().getName();
                log.info("capture device name:" + name);

                //设置分辨率
                Dimension viewSize = webcam.getViewSize();
                int nowWidth = viewSize.width;
                int nowHeight = viewSize.height;
                File targetFile = new File(targetPath);
                String fullPath = FilenameUtils.getFullPath(targetPath);
                File file = new File(fullPath);
                if (!file.exists()) {
                    file.mkdirs();
                }

                log.info("real resolution" + nowWidth + "x" + nowHeight);
                long begin = System.currentTimeMillis();
                BufferedImage image = webcam.getImage();
                ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
                if (Objects.equals(way,"1")){
                    threadPool.submit(() -> {
                        log.info("begin async persistent img");
                        persistentImg(captureQuery, targetFile, writer, image);
                    });
                }else {
                    persistentImg(captureQuery, targetFile, writer, image);
                }
                

                long endTime = System.currentTimeMillis();
                log.info("costTime:" + (endTime - begin));

            } catch (Exception e) {
                log.error(ThrowableUtil.getStackTrace(e));
                return false;
            }
        }
        return true;
    }

    private static void persistentImg(CaptureQuery captureQuery, File targetFile, ImageWriter writer, BufferedImage image) {
        try (ImageOutputStream ios = ImageIO.createImageOutputStream(targetFile)) {
            writer.setOutput(ios);
            // 参数配置
            JPEGImageWriteParam param = new JPEGImageWriteParam(null);
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            param.setCompressionQuality(Convert.toFloat(captureQuery.getQuality()));
            // 写入图像
            writer.write(null, new IIOImage(image, null, null), param);
        }catch (Exception e){
            log.error(ThrowableUtil.getStackTrace(e));
        } finally {
            writer.dispose();
        }
    }

    /**
     * 官方示例
     * @param captureQuery
     * @return
     */
    //public static boolean captureStandard(CaptureQuery captureQuery) {
    //
    //    String deviceFlag = captureQuery.getDeviceFlag();
    //    String targetPath = captureQuery.getTargetPath();
    //    Webcam webcam = FLAG_WEBCAM_MAP.get(deviceFlag);
    //    if (webcam != null) {
    //        try {
    //
    //            String name = webcam.getDevice().getName();
    //            log.info("截图设备名称:" + name);
    //
    //            //设置分辨率
    //            Dimension viewSize = webcam.getViewSize();
    //            int nowWidth = viewSize.width;
    //            int nowHeight = viewSize.height;
    //            File targetFile = new File(targetPath);
    //            String fullPath = FilenameUtils.getFullPath(targetPath);
    //            File file = new File(fullPath);
    //            if (!file.exists()) {
    //                file.mkdirs();
    //            }
    //
    //            log.info("实际分辨率" + nowWidth + "x" + nowHeight);
    //
    //            long begin = System.currentTimeMillis();
    //            BufferedImage image = webcam.getImage();
    //            ImageIO.write(image, "jpg", targetFile);
    //            long endTime = System.currentTimeMillis();
    //            log.info("costTime:" + (endTime - begin));
    //
    //        } catch (Exception e) {
    //            log.error(ThrowableUtil.getStackTrace(e));
    //            return false;
    //        }
    //    }
    //    return true;
    //}


}

